package com.rzgeo.rzmaplib.comp;

import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.CompoundButton;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;

import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.Field;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.data.ShapefileFeatureTable;
import com.esri.arcgisruntime.geometry.Envelope;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.mapping.view.GeoView;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.mapping.view.NavigationChangedEvent;
import com.esri.arcgisruntime.mapping.view.NavigationChangedListener;
import com.rzgeo.rzmaplib.R;
import com.rzgeo.rzmaplib.comp.geoview.IRmlGeoViewHolder;
import com.rzgeo.rzmaplib.media.IRmlCameraProvider;
import com.rzgeo.rzmaplib.model.RmlPrj;
import com.rzgeo.rzmaplib.util.RmlData;
import com.rzgeo.rzmaplib.util.RmlUtil;

import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ExecutionException;

/**
 * Created by zhanghang on 2018/1/28.
 */

public class RmlTaskList extends FrameLayout {
    private ListView _listView;
    private FeatureLayer _taskLayer;
    private List<FeatureLayer> _optionalLayer;
    private RmlPrj.EditMap _editMap;
    private Activity _activity;
    private IRmlGeoViewHolder _geoViewHolder;
    private IRmlCameraProvider _cameraProvider;
    private TaskListToolBar _toolBar;
    private View rl_tasklist;
    private RmlTaskEditor rte_task_editor;
    private RmlPhotosViewer rte_photo_viewer;

    public RmlTaskList(@NonNull Context context) {
        super(context);
        initUI(context);
    }

    public RmlTaskList(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initUI(context);
    }


    public RmlTaskList(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initUI(context);
    }

    private void initUI(Context context) {
        View subView = LayoutInflater.from(context).inflate(R.layout.comp_task_list, null);
        subView.setLayoutParams(
                new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        this.addView(subView);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        rl_tasklist = findViewById(R.id.rl_tasklist);
        rte_task_editor = findViewById(R.id.rte_task_editor);
        rte_photo_viewer = findViewById(R.id.rte_photo_viewer);

        switchViews (0);

        _listView = findViewById(R.id.listview);
        _listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                setZoom2Task((Feature) _listView.getAdapter().getItem(position),RmlTaskList.this.getVisibility()==VISIBLE);
            }
        });
        _toolBar=new TaskListToolBar(this,getContext());
    }

    private void switchViews(int i) {
        if(i==0){
            rl_tasklist.setVisibility(VISIBLE);
            rte_task_editor.setVisibility(GONE);
            rte_photo_viewer.setVisibility(GONE);
        }else if(i==1){
            rl_tasklist.setVisibility(INVISIBLE);
            rte_task_editor.setVisibility(VISIBLE);
            rte_photo_viewer.setVisibility(GONE);
        }else if(i==2){
            rl_tasklist.setVisibility(INVISIBLE);
            rte_task_editor.setVisibility(INVISIBLE);
            rte_photo_viewer.setVisibility(VISIBLE);
        }
    }

    private void setZoom2Task(Feature taskFeature,boolean withPadding) {
        Map<String, Object> attrs=taskFeature.getAttributes();
        String layerName= RmlUtil.Dict.getString(attrs,TaskStruct.FnLAYERNAME);
        String layerFId=RmlUtil.Dict.getString(attrs,TaskStruct.FnLAYERFID);

        FeatureLayer tl = null;
        for (FeatureLayer tfl : _optionalLayer) {
            if (tfl.getName().equalsIgnoreCase(layerName)) {
                tl = tfl;
                break;
            }
        }

        final float padFact = withPadding?1.0f *this.getWidth() /this._geoViewHolder.getGeoView().getWidth():1;

        if (tl == null) {
            RmlUtil.Tip.Toast("未发现图层:" + layerName);
            return;
        }
        final FeatureLayer targetLayer = tl;

        QueryParameters qp = new QueryParameters();
        qp.getObjectIds().add(RmlUtil.Convert.toLong(layerFId));

        final ListenableFuture<FeatureQueryResult> ff = tl.selectFeaturesAsync(qp, FeatureLayer.SelectionMode.NEW);
        ff.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    ff.get();
                    final ListenableFuture<FeatureQueryResult> sf = targetLayer.getSelectedFeaturesAsync();
                    sf.addDoneListener(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                FeatureQueryResult sfr = sf.get();
                                Iterator<Feature> iterator = sfr.iterator();
                                ArrayList<Feature> features = new ArrayList<>();
                                Feature feature=null;
                                while (iterator.hasNext()) {
                                    feature=iterator.next();
                                }
                                if(feature!=null)
                                {
                                    Envelope ext = feature.getGeometry().getExtent();
                                    Envelope paddingExt=new Envelope(ext.getXMin(),ext.getYMin(),
                                            ext.getXMax()+(1+padFact)*ext.getWidth(),
                                            ext.getYMax(),
                                            ext.getSpatialReference());
                                    _geoViewHolder.setViewExtent(paddingExt);
                                }
                            } catch (Exception e) {
                                RmlUtil.Log.Err(e);
                            }
                        }
                    });
                } catch (Exception e) {
                    RmlUtil.Log.Err(e);
                }
            }
        });
    }

    public void setup(final Activity activity,
                      RmlPrj.EditMap editMap,
                      List<FeatureLayer> optionalLayer,
                      IRmlGeoViewHolder geoViewHolder,
                      IRmlCameraProvider cameraProvider) {
        _activity = activity;
        _editMap = editMap;
        _taskLayer = editMap.getTaskLayer();

        _optionalLayer = optionalLayer;
        _geoViewHolder = geoViewHolder;
        _toolBar.setGeoViewHolder(geoViewHolder);
        _cameraProvider = cameraProvider;

        QueryParameters qp = new QueryParameters();
        updateList(true,_toolBar.getQueryParamters());
    }

    public void updateTask(){
        UpdateTask.update(_taskLayer, _optionalLayer, new UpdateTask.OnResult() {
            @Override
            public void onFisnih() {

                updateList(false, _toolBar.getQueryParamters());
            }

            @Override
            public void onFaild(String msg, Exception e) {
                RmlUtil.Log.Err("更新失败");

            }
        });
    }

    private void updateList(final boolean tipIfNoResult, QueryParameters qp) {
//        updateTask();
        final ListenableFuture<FeatureQueryResult> ff = _taskLayer.getFeatureTable().queryFeaturesAsync(qp);
        ff.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    FeatureQueryResult fr = ff.get();

                    TaskStruct.initFields(fr.getFields());

                    Iterator<Feature> iterator = fr.iterator();
                    ArrayList<Feature> features = new ArrayList<>();
                    while (iterator.hasNext()) {
                        features.add(iterator.next());
                    }
                    if (features.size() == 0 && _optionalLayer.size() != 0&&tipIfNoResult) {
                        RmlUtil.Dialog.Choice(_activity, "你的任务列表为空，是否刷新?", new RmlUtil.Dialog.OnChoice() {
                            @Override
                            public void onResult(boolean confirm) {
                                if (confirm) {
                                    updateTask();
                                }
                            }
                        });
                    } else {
                        _listView.setAdapter(
                                new Adapte(_activity, features, fr.getFields(), _geoViewHolder, _cameraProvider));
                    }

                } catch (Exception e) {
                    RmlUtil.Log.Err(e);
                }
            }
        });
    }

    public List<FeatureLayer> getOptionLayer() {
        return _optionalLayer;
    }

    public void addNewPhoto(File photo, Date date, Feature taskFeature) {

    }


    public static class TaskStruct {
        public static final String State1NotSurvey="未调查";
        public static final String State2FoundNotChanged="未变动";
        public static final String State3FoundNotExsit="消失了";
        public static final String State4FoundChanged="变化了";
        public static final String State5CannotHandle="未处理";
        public static String FnFid = null;
        public static String FnLAYERNAME = "LAYERNAME";
        public static String FnLAYERFID = "LAYERFID";
        public static String FnLAYERUID = "LAYERUID";
        public static String FnUID = "UID";
        public static String FnCODE1 = "CODE1";
        public static String FnCODE2 = "CODE2";
        public static String FnCODE3 = "CODE3";
        public static String FnCODE4 = "CODE4";
        public static String FnEXLABEL1 = "EXLABEL1";
        public static String FnEXLABEL2 = "EXLABEL2";
        public static String FnEXLABEL3 = "EXLABEL3";
        public static String FnEXLABEL4 = "EXLABEL4";
        public static String FnREMARK = "REMARK";
        public static String FnSTATE="STATE";
        private TaskStruct(){

        }

        public static String[]getStates(){
            return new String[]{State1NotSurvey,State2FoundNotChanged,State3FoundNotExsit,State4FoundChanged,State5CannotHandle};
        }
//        public String vFid = null;
//        public String vLAYERNAME = null;
//        public String vLAYERFID = null;
//        public String vLAYERUID = null;
//        public String vUID = null;
//        public String vCODE1 = null;
//        public String vCODE2 = null;
//        public String vCODE3 = null;
//        public String vCODE4 = null;
//        public String vEXLABEL1 = null;
//        public String vEXLABEL2 = null;
//        public String vEXLABEL3 = null;
//        public String vEXLABEL4 = null;
//        public String vREMARK = null;


//        public static TaskStruct[] fromFeature(ArrayList<Feature> features, List<Field> fields) {
//            if (FnFid == null) {
//                initFields(fields);
//            }
//            TaskStruct[] tasks = new TaskStruct[features.size()];
//            for (int i = 0; i < features.size(); i++) {
//                tasks[i] = innerFromFeature(features.get(i),fields);
//
//            }
//            return tasks;
//        }


//        public static final TaskStruct fromFeature(Feature feature, List<Field> fields) {
//            if (FnFid == null) {
//                initFields(fields);
//            }
//            return innerFromFeature(feature,fields);
//        }

//        private static final TaskStruct innerFromFeature(Feature feature, List<Field> fields) {
//            TaskStruct tb = new TaskStruct();
//            Map<String, Object> attrs = feature.getAttributes();
//            tb.vFid = RmlUtil.Convert.toString(attrs.get(
//                    FnFid));
//            tb.vLAYERNAME = RmlUtil.Convert.toString(attrs.get(
//                    FnLAYERNAME));
//            tb.vLAYERFID = RmlUtil.Convert.toString(attrs.get(
//                    FnLAYERFID));
//            tb.vLAYERUID = RmlUtil.Convert.toString(attrs.get(
//                    FnLAYERUID));
//            tb.vUID = RmlUtil.Convert.toString(attrs.get(
//                    FnUID));
//            tb.vCODE1 = RmlUtil.Convert.toString(attrs.get(
//                    FnCODE1));
//            tb.vCODE2 = RmlUtil.Convert.toString(attrs.get(
//                    FnCODE2));
//            tb.vCODE3 = RmlUtil.Convert.toString(attrs.get(
//                    FnCODE3));
//            tb.vCODE4 = RmlUtil.Convert.toString(attrs.get(
//                    FnCODE4));
//            tb.vEXLABEL1 = RmlUtil.Convert.toString(attrs.get(
//                    FnEXLABEL1));
//            tb.vEXLABEL2 = RmlUtil.Convert.toString(attrs.get(
//                    FnEXLABEL2));
//            tb.vEXLABEL3 = RmlUtil.Convert.toString(attrs.get(
//                    FnEXLABEL3));
//            tb.vEXLABEL4 = RmlUtil.Convert.toString(attrs.get(
//                    FnEXLABEL4));
//            tb.vREMARK = RmlUtil.Convert.toString(attrs.get(
//                    FnREMARK));
//            return tb;
//        }

//        private static final void innerToFeature(TaskStruct tb,Feature feature) {
//
//            Map<String, Object> attrs = feature.getAttributes();
//             attrs.put(
//                    FnLAYERNAME,tb.vLAYERNAME);
//             attrs.put(
//                    FnLAYERFID,tb.vLAYERFID);
//            attrs.put(
//                    FnLAYERUID,tb.vLAYERUID);
//             attrs.put(
//                    FnUID,tb.vUID);
//             attrs.put(
//                    FnCODE1,tb.vCODE1);
//             attrs.put(
//                    FnCODE2,tb.vCODE2);
//             attrs.put(
//                    FnCODE3,tb.vCODE3);
//             attrs.put(
//                    FnCODE4,tb.vCODE4);
//             attrs.put(
//                    FnEXLABEL1,tb.vEXLABEL1);
//             attrs.put(
//                    FnEXLABEL2,tb.vEXLABEL2);
//             attrs.put(
//                    FnEXLABEL3,tb.vEXLABEL3);
//             attrs.put(
//                    FnEXLABEL4,tb.vEXLABEL4);
//             attrs.put(
//                    FnREMARK,tb.vREMARK);
//
//        }
        public static void initFields(List<Field> fields) {
            for (Field f : fields) {
                if (f.getFieldType() == Field.Type.OID)
                    FnFid = f.getName();
                else if (FnLAYERNAME.equalsIgnoreCase(f.getName()))
                    FnLAYERNAME = f.getName();
                else if (FnLAYERFID.equalsIgnoreCase(f.getName()))
                    FnLAYERFID = f.getName();
                else if (FnLAYERUID.equalsIgnoreCase(f.getName()))
                    FnLAYERUID = f.getName();
                else if (FnUID.equalsIgnoreCase(f.getName()))
                    FnUID = f.getName();
                else if (FnCODE1.equalsIgnoreCase(f.getName()))
                    FnCODE1 = f.getName();
                else if (FnCODE2.equalsIgnoreCase(f.getName()))
                    FnCODE2 = f.getName();
                else if (FnCODE3.equalsIgnoreCase(f.getName()))
                    FnCODE3 = f.getName();
                else if (FnCODE4.equalsIgnoreCase(f.getName()))
                    FnCODE4 = f.getName();
                else if (FnEXLABEL1.equalsIgnoreCase(f.getName()))
                    FnEXLABEL1 = f.getName();
                else if (FnEXLABEL2.equalsIgnoreCase(f.getName()))
                    FnEXLABEL2 = f.getName();
                else if (FnEXLABEL3.equalsIgnoreCase(f.getName()))
                    FnEXLABEL3 = f.getName();
                else if (FnEXLABEL4.equalsIgnoreCase(f.getName()))
                    FnEXLABEL4 = f.getName();
                else if (FnREMARK.equalsIgnoreCase(f.getName()))
                    FnREMARK = f.getName();
                else if (FnSTATE.equalsIgnoreCase(f.getName()))
                    FnSTATE = f.getName();
            }
        }

        public static void newTaskFeature(String layerName, String fid, Feature f, Feature newTaskFeature) {
            Point labPon=
                RmlUtil.Geo.getLabelPoint(f.getGeometry());
            newTaskFeature.setGeometry(labPon);

            Map<String, Object> attrs = newTaskFeature.getAttributes();
            attrs.put(FnLAYERNAME,layerName);
            attrs.put(FnLAYERFID,fid);
            attrs.put(FnUID,RmlUtil.getUid());
            attrs.put(FnSTATE,TaskStruct.State1NotSurvey);
        }
    }

    public static class UpdateTask extends AsyncTask<Void, Integer, Void> {
        final ArrayList<Feature> task2Remove = new ArrayList<>(128);
        private final RmlUtil.Loader.Query[] _qs;
        private final OnResult _onResult;
        ArrayList<Feature> taskFeature2Add = new ArrayList<>(128);
        private Exception _e=null;
        private UpdateTask(RmlUtil.Loader.Query[] qs, OnResult onResult) {
            super();
            _qs = qs;
            _onResult=onResult;
        }

        public static void update(FeatureLayer taskLayer, List<FeatureLayer> optionalLayer, final OnResult onResult) {
            QueryParameters qp = new QueryParameters();
            qp.setReturnGeometry(true);

            final RmlUtil.Loader.Query[] qs = new RmlUtil.Loader.Query[optionalLayer.size() + 1];
            for (int i = 0; i < optionalLayer.size(); i++) {
                FeatureLayer fl = optionalLayer.get(i);
                qs[i] = new RmlUtil.Loader.Query(fl.getFeatureTable(), qp, new RmlUtil.Loader.Query.QueryFeatureResult());
            }

            qs[qs.length - 1] = new RmlUtil.Loader.Query(
                    taskLayer.getFeatureTable(),
                    qp,
                    new RmlUtil.Loader.Query.QueryFeatureResult());

            RmlUtil.Loader.load(qs, new RmlUtil.Loader.OnResult() {
                @Override
                public void onFinish(Map<RmlUtil.Loader.LoadaebleItem, RmlUtil.Loader.LoadResult> refs2LoadResult) {

                    UpdateTask task = new UpdateTask(qs,onResult);
                    task.execute();
                }
            });
        }

        private static final String getKey(String vLAYERNAME, String vLAYERFID) {
            return vLAYERNAME + "_" + vLAYERFID;
        }

        @Override
        protected Void doInBackground(Void... voids) {

            try {

                RmlUtil.Loader.Query.QueryFeatureResult tResult = (RmlUtil.Loader.Query.QueryFeatureResult) _qs[_qs.length - 1]._result;

                HashMap<String, Feature> key_TaskFeatureMap = new HashMap<>(tResult.features.size());
                Set<String> allFeatureKeys = new HashSet(1024);

                TaskStruct.initFields(tResult.fields);
                for (Feature f : tResult.features) {
                    Map<String, Object> attr = f.getAttributes();
                    key_TaskFeatureMap.put(getKey(
                            RmlUtil.Dict.getString(attr,TaskStruct.FnLAYERNAME),
                            RmlUtil.Dict.getString(attr,TaskStruct.FnLAYERFID)),
                            f);
                }
                //扫描源图层，找到需要添加的要素，并初始化当前图层key索引用于删除任务列表
                final FeatureTable tTable = _qs[_qs.length - 1]._table;

                for (int i = 0; i < _qs.length - 1; i++) {
                    RmlUtil.Loader.Query.QueryFeatureResult sResult = (RmlUtil.Loader.Query.QueryFeatureResult) _qs[i]._result;
                    String fidFieldName = RmlUtil.Features.getFIDField(sResult.fields).getName();
                    String layerName;
                    if (_qs[i]._table instanceof ShapefileFeatureTable)
                        layerName = new File(((ShapefileFeatureTable) _qs[i]._table).getPath()).getName();
                    else
                        layerName = _qs[i]._table.getTableName();

                    for (Feature f : sResult.features) {
                        String sfid = RmlUtil.Dict.getString(f.getAttributes(), fidFieldName);
                        String skey = getKey(layerName,sfid);

                        allFeatureKeys.add(skey);

                        if (!key_TaskFeatureMap.containsKey(skey)){
                            Feature nf=tTable.createFeature();
                            TaskStruct.newTaskFeature(layerName,sfid,f,nf);
                            taskFeature2Add.add(nf);
                        }
                    }
                }

                for (String key : key_TaskFeatureMap.keySet()) {
                    if (!allFeatureKeys.contains(key))
                        task2Remove.add(key_TaskFeatureMap.get(key));
                }
            }catch (Exception e){
                _e=e;
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);

            if(_e!=null){
                _onResult.onFaild("异步统计时发生异常",_e);
            }

            final FeatureTable tTable = _qs[_qs.length - 1]._table;
            final ListenableFuture<Void> ta = tTable.addFeaturesAsync(taskFeature2Add);
            ta.addDoneListener(new Runnable() {
                @Override
                public void run() {
                    try {
                        ta.get();
                        final ListenableFuture<Void> td = tTable.deleteFeaturesAsync(task2Remove);
                        td.addDoneListener(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    td.get();
                                    _onResult.onFisnih();
                                } catch (Exception e) {
                                    RmlUtil.Log.Err(e);
                                    _onResult.onFaild("删除旧任务数据时异常",e);
                                }
                            }
                        });
                    } catch (Exception e) {
                        RmlUtil.Log.Err(e);
                        _onResult.onFaild("添加新任务数据时异常",e);
                    }
                }
            });
        }

        public interface OnResult{
            void onFisnih();
            void onFaild(String msg,Exception e);
        }
    }

    private static class TaskListToolBar implements NavigationChangedListener {
        private final RmlTaskList _rmlTaskList;
        private final View _btn_conf;
        private final Switch _sw_filter_extent;
        private final Switch _sw_filter_layer_visible;
        private final Spinner _sp_filter_state;


//        private static final String FilterStates[]={"全部","未核查","已核查","不确定"};
        private final Context _context;
        private final String[] _stateFiltrTitles;
        private IRmlGeoViewHolder _geoViewHolder;

        public TaskListToolBar(RmlTaskList rmlTaskList,Context context) {
            _context=context;
            _rmlTaskList=rmlTaskList;

            _btn_conf=_rmlTaskList.findViewById(R.id.btn_conf);
            _sw_filter_extent=_rmlTaskList.findViewById(R.id.sw_filter_extent);
            _sw_filter_layer_visible=_rmlTaskList.findViewById(R.id.sw_filter_layer_visible);
            _sp_filter_state=_rmlTaskList.findViewById(R.id.sp_filter_state);

            String[] states = TaskStruct.getStates();
            _stateFiltrTitles = new String[states.length + 1];
            _stateFiltrTitles[0]="全部";
            System.arraycopy(states,0,_stateFiltrTitles,1,states.length);

            _btn_conf.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    RmlUtil.Dialog.Choice(_context, "任务列表操作", "删除", "更新", new RmlUtil.Dialog.OnChoice2() {
                        @Override
                        public void onPosi() {
                            _rmlTaskList.updateTask();
                        }

                        @Override
                        public void onNeut() {
                            RmlUtil.Dialog.Choice(_context, "您确定要删除所有的调查任务？已经采集的任务信息也会一同删除掉", new RmlUtil.Dialog.OnChoice() {
                                @Override
                                public void onResult(boolean confirm) {
                                    if(confirm){
                                        _rmlTaskList.deleteAllTask();
                                    }
                                }
                            });

                        }

                        @Override
                        public void onCancel() {

                        }
                    });
                }
            });

            _sw_filter_extent.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    if(isChecked) {
                        _geoViewHolder.getGeoView().addNavigationChangedListener(TaskListToolBar.this);
                        filterData();
                    }
                    else
                        _geoViewHolder.getGeoView().removeNavigationChangedListener(TaskListToolBar.this);
                }
            });

            _sw_filter_layer_visible.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                    filterData();
                }
            });



            ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                    _context,
                    android.R.layout.simple_spinner_item,
                    _stateFiltrTitles);
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            _sp_filter_state.setAdapter(adapter);
            _sp_filter_state.setSelection(0);
            _sp_filter_state.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener(){

                @Override
                public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                    filterData();
                }

                @Override
                public void onNothingSelected(AdapterView<?> parent) {

                }
            });
        }

        public QueryParameters getQueryParamters() {
            QueryParameters qp=new QueryParameters();

            if(_sw_filter_extent.isChecked())
            {
                GeoView gv = _geoViewHolder.getGeoView();
                if(gv instanceof MapView){
                    qp.setGeometry(((MapView)gv).getVisibleArea());
                }
            }

            int isel = _sp_filter_state.getSelectedItemPosition();

            if(isel>0){
                qp.setWhereClause(
                String.format("%s like '%s'",TaskStruct.FnSTATE,
                        _stateFiltrTitles[isel]));
            }

            if(_sw_filter_layer_visible.isChecked())
            {
                ArrayList<String>layerNames=new ArrayList<>();
                List<FeatureLayer> layers = _rmlTaskList.getOptionLayer();
                for (FeatureLayer l:layers
                     ) {
                    if(l.isVisible()){
                        layerNames.add(String.format("%s like '%s'",TaskStruct.FnLAYERNAME,RmlUtil.Layers.getName(l)));
                    }
                }
                String where = qp.getWhereClause();
                if(where.length()>5){
                    qp.setWhereClause(
                            String.format("%s AND (%s)",where,
                                    TextUtils.join(" OR ",layerNames)));
                }else{
                    qp.setWhereClause(
                            String.format("%s",
                                    TextUtils.join(" OR ",layerNames)));
                }
            }
            return qp;
        }

        private void filterData() {
            _rmlTaskList.updateList(
                    false,
                    getQueryParamters());
        }

        public void setGeoViewHolder(IRmlGeoViewHolder geoViewHolder) {
            this._geoViewHolder = geoViewHolder;
        }

        @Override
        public void navigationChanged(NavigationChangedEvent e) {
            if(!e.isNavigating()){
                filterData();
            }
        }

        public boolean isWithLayerVisible() {
            return _sw_filter_layer_visible.isChecked();
        }
    }

    private void deleteAllTask() {
        QueryParameters qp = new QueryParameters();
        qp.setReturnGeometry(false);

        RmlUtil.Features.queryAndDelete(_taskLayer.getFeatureTable(), qp,
                new RmlUtil.Features.OnDelResult() {
                    @Override
                    public void onResult(int numDel, int numDelFail) {
                        RmlUtil.Tip.Toast(String.format("删除%d个任务,%d个删除失败",numDel,numDelFail));
                    }

                    @Override
                    public void onFail() {
                        RmlUtil.Tip.Toast("删除失败");
                    }
                });
    }

    public class Adapte extends BaseAdapter {


        private final Context _context;
        private final LayoutInflater _inflater;
        private final IRmlGeoViewHolder _geoViewHolder;
        private final IRmlCameraProvider _cameraProvider;
//        private String OID = null;
//        private String FromLayer = null;
//        private String FromId = null;
//        private String Msg = null;
//        private String State = null;
//        private String Code = null;
//        private String UUID = null;
//        private String CreateTim = null;
//        private String EditTim = null;

        private final ArrayList<Feature> _features;

        public Adapte(Context context, ArrayList<Feature> features,
                      List<Field> fields,
                      IRmlGeoViewHolder geoViewHolder,
                      IRmlCameraProvider cameraProvider) {
            _features = features;
            _geoViewHolder = geoViewHolder;
            _context = context;
            _cameraProvider = cameraProvider;
            _inflater = LayoutInflater.from(_context);
            TaskStruct.initFields(fields);

        }

        @Override
        public int getCount() {
            return _features.size();
        }

        @Override
        public Object getItem(int position) {
            return _features.get(position);
        }

        @Override
        public long getItemId(int position) {
            return RmlUtil.Convert.toLong(_features.get(position).getAttributes().get(TaskStruct.FnFid));
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder;
            if (convertView == null) {
                convertView = _inflater.inflate(R.layout.comp_task_list_item, null);
                holder = new ViewHolder(convertView, _context, this);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
            holder.setData(_features.get(position));
            return convertView;
        }

        public class ViewHolder {
            private final TextView txv_fromlayer;
            private final TextView txv_fromid;
            private final TextView txv_state;
            private final TextView txv_remark;
            private final ImageView img_edit;
            private final ImageView img_photo;
            private final ImageView img_goto;
            private final Adapte _adapte;
            private Feature _taskFeature;

            public ViewHolder(View convertView, Context context, Adapte adapte) {

                _adapte = adapte;
                txv_fromlayer = convertView.findViewById(R.id.txv_fromlayer);
                txv_fromid = convertView.findViewById(R.id.txv_fromid);
                txv_state = convertView.findViewById(R.id.txv_state);
                txv_remark = convertView.findViewById(R.id.txv_remark);
                img_edit = convertView.findViewById(R.id.img_edit);
                img_photo = convertView.findViewById(R.id.img_photo);
                img_goto = convertView.findViewById(R.id.img_goto);
            }

            public void setData(Feature feature) {

                _taskFeature = feature;

                Map<String, Object> a = _taskFeature.getAttributes();
                txv_fromlayer.setText(RmlUtil.Dict.getString(a, TaskStruct.FnLAYERNAME));
                txv_fromid.setText(RmlUtil.Dict.getString(a, TaskStruct.FnLAYERFID));
                txv_state.setText(RmlUtil.Dict.getString(a, TaskStruct.FnSTATE));
                txv_remark.setText(RmlUtil.Dict.getString(a, TaskStruct.FnREMARK));

                img_edit.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        showEditor();
                        Map<String, Object> a = _taskFeature.getAttributes();
                        final String fromlayer = RmlUtil.Dict.getString(a, TaskStruct.FnLAYERNAME);
                        final String fromlayershp = RmlUtil.Dict.getString(a, TaskStruct.FnLAYERNAME) + ".shp";
                        final String fromid = RmlUtil.Dict.getString(a, TaskStruct.FnLAYERFID);

                        FeatureLayer targetLayer = null;
                        for (FeatureLayer tfl : _optionalLayer) {
                            if (tfl.getName().equalsIgnoreCase(fromlayer) ||
                                    tfl.getName().equalsIgnoreCase(fromlayershp)) {
                                targetLayer = tfl;
                                break;
                            }
                        }

                        showEditor();
                        if (targetLayer == null) {
                            RmlUtil.Tip.Toast("未发现图层:" + fromlayer);
                            return;
                        }

                        QueryParameters qp = new QueryParameters();
                        qp.getObjectIds().add(RmlUtil.Convert.toLong(fromid));

                        final ListenableFuture<FeatureQueryResult> ff = targetLayer.getFeatureTable().queryFeaturesAsync(qp);
                        final FeatureLayer finalTargetLayer = targetLayer;
                        ff.addDoneListener(new Runnable() {
                            @Override
                            public void run() {
                                try {
                                    FeatureQueryResult fr = ff.get();

                                    Iterator<Feature> iterator = fr.iterator();
                                    ArrayList<Feature> features = new ArrayList<>();
                                    while (iterator.hasNext()) {
                                        features.add(iterator.next());
                                    }

                                    if (features.size() > 1) {
                                        RmlUtil.Tip.Toast("对象ID不唯一或者:" + fromid);
                                        return;
                                    } else if (features.size() == 0) {
                                        RmlUtil.Tip.Toast("对象ID不唯一为空:" + fromid);
                                        return;
                                    }


//
                                    final RmlData.FeatureLayerData targetFeature = new RmlData.FeatureLayerData(features.get(0), finalTargetLayer);

//                                    RmlUtil.Dialog.EditAttrs(_context, targetFeature, new RmlUtil.Dialog.OnInputText() {
//                                        @Override
//                                        public void onResult(String content) {
//                                            _taskFeature.getAttributes().put(TaskStruct.FnSTATE, "已核查");
//                                            ListenableFuture<Void> ff2 = _taskLayer.getFeatureTable().updateFeatureAsync(_taskFeature);
//                                            ff2.addDoneListener(new Runnable() {
//                                                @Override
//                                                public void run() {
//                                                    _adapte.notifyDataSetChanged();
//                                                    RmlUtil.Tip.Toast("属性已经更新");
//                                                }
//                                            });
//
//                                        }
//
//                                        @Override
//                                        public void onCancel() {
//
//                                        }
//                                    });
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                } catch (ExecutionException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    }

                    private void showEditor()
                    {
                        switchViews(1);

                        rte_task_editor.setup(
                                _taskLayer, _taskFeature,
                                new RmlTaskEditor.OnResult() {
                                    public File _photo;

                                    @Override
                            public void onOK(Feature feature) {
                                notifyDataSetChanged();
                                switchViews(0);
                            }

                            @Override
                            public void onReset(Feature feature) {
//                                _adapte._features.(feature);
                                notifyDataSetChanged();
                            }

                            @Override
                            public void onDelete(Feature feature) {
                                _adapte._features.remove(feature);
                                notifyDataSetChanged();
                            }

                            @Override
                            public void onCancel() {
                                switchViews(0);
                            }

                            @Override
                            public void onTakePhoto(Feature taskFeature, File photoStrogeFile, RmlPhotosViewer.OnTakePhotoResult onResult) {
                                _geoViewHolder.getLocMgr().start(true, 500, 50,
                                        new IRmlGeoViewHolder.ILocMgr.OnRecodeResult() {
                                            @Override
                                            public void onFinish(Queue<IRmlGeoViewHolder.ILocMgr.Info> result) {
                                                 Date date=null;
                                                try {
//                                                    Metadata metadata = ImageMetadataReader.readMetadata(_photo.getAbsoluteFile());
//                                                    Iterator<Directory> it = metadata.getDirectories().iterator();
//                                                    while (it.hasNext()) {
//                                                        Directory exif = it.next();
//                                                        Iterator<Tag> tags = exif.getTags().iterator();
//                                                        while (tags.hasNext()) {
//                                                            Tag tag =  tags.next();
//                                                            RmlUtil.Log.Msg(tag.getTagName()+"--"+tag.getDescription());
//                                                            if("Date/Time".equalsIgnoreCase(tag.getTagName())){
//                                                                date=new Date(tag.getDescription());
//                                                            }
//                                                        }
//
//                                                    }
                                                } catch (Exception e) {
                                                    RmlUtil.Log.Err(e);
                                                }

                                                IRmlGeoViewHolder.ILocMgr.Info li = RmlUtil.Geo.calculateLocInfo(result, date);
                                                if(li==null){
                                                    RmlUtil.Tip.Toast("没有位置信息，请确保打开地图定位开关、授权app获取位置信息、并且GPS能够定位");
                                                    return;
                                                }

                                                Map<String, Object> attrs=new HashMap<>();
                                                attrs.put("ROLL",li.accelerometer[0]);
                                                attrs.put("PICTH",li.accelerometer[1]);
                                                attrs.put("YAW",li.location.getCourse());

                                                attrs.put("LNG",li.location.getPosition().getX());
                                                attrs.put("LAT",li.location.getPosition().getY());
                                                attrs.put("ALT",li.location.getPosition().getZ());

                                                attrs.put("NAME",_photo.getName());
                                                attrs.put("PATH",_photo.getPath());

                                                FeatureTable pt = _editMap.getPhotoLayer().getFeatureTable();
                                                if(!pt.canAdd())
                                                {
                                                    RmlUtil.Tip.Toast("数据错误，无法添加记录");
                                                    return;
                                                }
                                                Feature nf = pt.createFeature(attrs, li.location.getPosition());
                                                final ListenableFuture<Void> af = pt.addFeatureAsync(nf);
                                                af.addDoneListener(new Runnable() {
                                                    @Override
                                                    public void run() {
                                                        try {
                                                            af.get();
                                                        } catch (Exception e) {
                                                            RmlUtil.Log.Err(e);
                                                        }
                                                    }
                                                });
                                            }
                                });

                                String fileName = RmlUtil.Files.getPhotoName( _editMap.getPhotoFolder());
                                if(_cameraProvider==null)
                                    return;
                                _cameraProvider.takePhoto(
                                        fileName,
                                        new IRmlCameraProvider.OnFinish() {

                                            public void onResult(File photo, Date date) {
                                                _photo=photo;
                                                _geoViewHolder.getLocMgr().stop();
                                            }
                                });
                            }


                            @Override
                            public void onViewPhotos(Feature taskFeature, RmlPhotosViewer.OnResult onResult) {

                                QueryParameters qp=new QueryParameters();

                                qp.setWhereClause(
                                        String.format("%s like '%s'","",_taskFeature.getAttributes().get(TaskStruct.FnUID)));

                                rte_photo_viewer.setup(_editMap.getPhotoLayer(), qp, new RmlPhotosViewer.OnResult() {
                                    @Override
                                    public void onDelete(Feature feature) {
                                        switchViews(1);
                                    }

                                    @Override
                                    public void onCancel() {
                                        switchViews(1);
                                    }
                                });
                                switchViews(2);
                            }
                        });
                    }
                });

                img_photo.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {

                    }
                });

                img_goto.setOnClickListener(new OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        _geoViewHolder.setViewExtent(_taskFeature.getGeometry().getExtent());
                    }
                });
            }

        }
    }
}
